package org.proddevplm.helpers;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.Query;
import org.hibernate.Session;
import org.proddevplm.dao.data.designForX.DesignForX;
import org.proddevplm.dao.data.designForX.DfXGuidelines;
import org.proddevplm.dao.data.designForX.DfXImportances;
import org.proddevplm.dao.data.designInputs.CTQs;
import org.proddevplm.dao.data.designInputs.DesignElements;
import org.proddevplm.dao.data.designInputs.ProductFunctions;
import org.proddevplm.dao.data.requirements.Requirements;
import org.proddevplm.dao.data.stakeholders.Stakeholder;
import org.proddevplm.dao.util.HibernateUtil;

public class ToolsUtil {
	
	public static float[] ahpMatrixCalculus(int matrixSize, float[][] ahpMatrix){
		
		float[] columnSum = new float[matrixSize];
		float[] importances = new float[matrixSize];
		
		for(int j=0; j<matrixSize; j++){
			float sum = 0;
			for(int i=0; i<matrixSize; i++){
				sum+=ahpMatrix[i][j];
			}
			columnSum[j]=sum;
			System.out.println("Suma pe coloana "+j+" este: "+columnSum[j]);
		}
		
		float[][] newMatrix = new float[matrixSize][matrixSize];
		for(int i=0; i<matrixSize; i++){
			for(int j=0; j<matrixSize; j++){
				newMatrix[i][j] = ahpMatrix[i][j]/columnSum[j];
			}
		}
		
		for(int i=0; i<matrixSize; i++){
			float sum = 0;
			for(int j=0; j<matrixSize; j++){
				sum+=newMatrix[i][j];
			}
			importances[i] = sum/matrixSize;
			System.out.println("Importanta elementului "+i+" este: "+importances[i]);
		}
		return importances;
	}
	
	public static Map<String, Object> pughMatrixCalculus(int rows, int cols, String[] criteriaImportances, String matrixValues){
		
		Map<String, Object> pughMap = new HashMap<String, Object>();
		System.out.println("randuri= "+rows+" coloane= "+cols+" matrixValues= "+matrixValues);
		float[] conceptsImportances = new float[cols];
		String[] matrixArray = matrixValues.split("~");
		float[][] pughMatrix = new float[rows][cols];
		float[] positiveEffects = new float[cols];
		float[] negativeEffects = new float[cols];
				
		int i=0; int j=0;
		int cont = 0;
		for(int index=0; index<matrixArray.length; index++){
			
			float value = Float.valueOf(matrixArray[index]);
			if(cont==(cols-1)){
				pughMatrix[i][j] = value;
				i++;
				j=0;
				cont=0;
			}else{
				pughMatrix[i][j] = value;
				j++;
				cont++;
			}
		}
		
		
		for(int k=0; k<cols; k++){
			float sum = 0;
			float positive = 0;
			float negative = 0; 
			for(int r=0; r<rows; r++){
				if(pughMatrix[r][k]<0){
					negative += pughMatrix[r][k]*Float.valueOf(criteriaImportances[r]);
				}else if (pughMatrix[r][k]>0){
					positive += pughMatrix[r][k]*Float.valueOf(criteriaImportances[r]);
				}
				
				sum+=pughMatrix[r][k]*Float.valueOf(criteriaImportances[r]);
			}
			positiveEffects[k] = positive;
			negativeEffects[k] = negative;
			conceptsImportances[k] = sum;
		}
		pughMap.put("positiveEffects", positiveEffects);
		pughMap.put("negativeEffects", negativeEffects);
		pughMap.put("netEffects", conceptsImportances);
		
		for(int k=0; k<cols; k++){
			System.out.println("Positive effect: "+positiveEffects[k]+" Negative effect: "+negativeEffects[k]+"Net effect= "+conceptsImportances[k]);
		}
		return pughMap;
	}
	
	public static float[] qfdMatrixCalculus(Object rows, Object cols, String[] qfdMatrix, String qfdType, int productId){
		Object qfdResults = null;
		
		if("reqVsCtqs".equals(qfdType)){
			List<Requirements> reqs = (List<Requirements>)rows;
			List<CTQs> ctqs = (List<CTQs>)cols;
			float[] results = new float[ctqs.size()];
			float[][] matrix = new float[reqs.size()][ctqs.size()];
			float[] colWeights = new float[ctqs.size()];
			float weightsSum = 0;
			
			int i=0; int j=0;
			int cont = 0;
			for(int index=0; index<qfdMatrix.length; index++){
				
				float value = Float.valueOf(qfdMatrix[index]);
				if(cont==(ctqs.size()-1)){
					matrix[i][j] = value;
					i++;
					j=0;
					cont=0;
				}else{
					matrix[i][j] = value;
					j++;
					cont++;
				}
			}
			
			for(int k=0; k<ctqs.size(); k++){
				float res = 0;
				for(int r=0; r<reqs.size(); r++){
					Requirements req = reqs.get(r);
					res+=matrix[r][k]*Float.valueOf(req.getImportance());
				}
				colWeights[k] = res;
			}
			
			for(int k=0; k<ctqs.size(); k++){
				weightsSum+=colWeights[k];
			}
			
			for(int k=0; k<ctqs.size(); k++){
				results[k] = (colWeights[k]/weightsSum)*100;
			}
			
			qfdResults = results;
			
		}else if("ctqsVsFunctions".equals(qfdType)){
			List<CTQs> ctqs = (List<CTQs>)rows;
			List<ProductFunctions> functions = (List<ProductFunctions>)cols;
			float[] results = new float[functions.size()];
			float[][] matrix = new float[ctqs.size()][functions.size()];
			float[] colWeights = new float[functions.size()];
			float weightsSum = 0;
			
			int i=0; int j=0;
			int cont = 0;
			for(int index=0; index<qfdMatrix.length; index++){
				
				float value = Float.valueOf(qfdMatrix[index]);
				if(cont==(functions.size()-1)){
					matrix[i][j] = value;
					i++;
					j=0;
					cont=0;
				}else{
					matrix[i][j] = value;
					j++;
					cont++;
				}
			}
			
			for(int k=0; k<functions.size(); k++){
				float res = 0;
				for(int r=0; r<ctqs.size(); r++){
					CTQs ctq = ctqs.get(r);
					res+=matrix[r][k]*Float.valueOf(ctq.getImportance());
				}
				colWeights[k] = res;
			}
			
			for(int k=0; k<functions.size(); k++){
				weightsSum+=colWeights[k];
			}
			
			for(int k=0; k<functions.size(); k++){
				results[k] = (colWeights[k]/weightsSum)*100;
			}
			
			qfdResults = results;
		
		}else if("functionsVsDEs".equals(qfdType)){
			List<ProductFunctions> functions = (List<ProductFunctions>)rows;
			List<DesignElements> des = (List<DesignElements>)cols;
			float[] results = new float[des.size()];
			float[][] matrix = new float[functions.size()][des.size()];
			float[] colWeights = new float[des.size()];
			float weightsSum = 0;
			
			int i=0; int j=0;
			int cont = 0;
			for(int index=0; index<qfdMatrix.length; index++){
				
				float value = Float.valueOf(qfdMatrix[index]);
				if(cont==(des.size()-1)){
					matrix[i][j] = value;
					i++;
					j=0;
					cont=0;
				}else{
					matrix[i][j] = value;
					j++;
					cont++;
				}
			}
			
			for(int k=0; k<des.size(); k++){
				float res = 0;
				for(int r=0; r<functions.size(); r++){
					ProductFunctions pf = functions.get(r);
					res+=matrix[r][k]*Float.valueOf(pf.getImportance());
				}
				colWeights[k] = res;
			}
			
			for(int k=0; k<des.size(); k++){
				weightsSum+=colWeights[k];
			}
			
			for(int k=0; k<des.size(); k++){
				results[k] = (colWeights[k]/weightsSum)*100;
			}
			
			qfdResults = results;
			
		}else if("shVsDFX".equals(qfdType)){
			List<Stakeholder> stakeholders = (List<Stakeholder>)rows;
			List<DesignForX> dfxs = (List<DesignForX>)cols;
			
			float[] results = new float[dfxs.size()];
			float[][] matrix = new float[stakeholders.size()][dfxs.size()];
			float[] colWeights = new float[dfxs.size()];
			float weightsSum = 0;
			
			int i=0; int j=0;
			int cont = 0;
			for(int index=0; index<qfdMatrix.length; index++){
				
				float value = Float.valueOf(qfdMatrix[index]);
				if(cont==(dfxs.size()-1)){
					matrix[i][j] = value;
					i++;
					j=0;
					cont=0;
				}else{
					matrix[i][j] = value;
					j++;
					cont++;
				}
			}
			
			for(int k=0; k<dfxs.size(); k++){
				float res = 0;
				for(int r=0; r<stakeholders.size(); r++){
					Stakeholder sh = stakeholders.get(r);
					res+=matrix[r][k]*Float.valueOf(sh.getImportance());
				}
				colWeights[k] = res;
			}
			
			for(int k=0; k<dfxs.size(); k++){
				weightsSum+=colWeights[k];
			}
			
			for(int k=0; k<dfxs.size(); k++){
				results[k] = (colWeights[k]/weightsSum)*100;
			}
			
			qfdResults = results;
			
		}else if("dfxVsGuidelines".equals(qfdType)){
			List<DesignForX> dfxs = (List<DesignForX>)rows;
			List<DfXGuidelines> dfxGuidelines = (List<DfXGuidelines>)cols;
			
			float[] results = new float[dfxGuidelines.size()];
			float[][] matrix = new float[dfxs.size()][dfxGuidelines.size()];
			float[] colWeights = new float[dfxGuidelines.size()];
			float weightsSum = 0;
			
			int i=0; int j=0;
			int cont = 0;
			for(int index=0; index<qfdMatrix.length; index++){
				
				float value = Float.valueOf(qfdMatrix[index]);
				if(cont==(dfxGuidelines.size()-1)){
					matrix[i][j] = value;
					i++;
					j=0;
					cont=0;
				}else{
					matrix[i][j] = value;
					j++;
					cont++;
				}
			}
			
			List<DfXImportances> dfxImp = getImportancesByProdId(productId);
			
			for(int k=0; k<dfxGuidelines.size(); k++){
				float res = 0;
				for(int r=0; r<dfxs.size(); r++){
					DesignForX dfx = dfxs.get(r);
					String importance = "";
					for(int index=0; index<dfxImp.size(); index++){
						DfXImportances dfxi = dfxImp.get(index);
						if(dfxi.getDfx()==dfx){
							importance = dfxi.getImportance();
							continue;
						}
					}
					res+=matrix[r][k]*Float.valueOf(importance);
				}
				colWeights[k] = res;
			}
			
			for(int k=0; k<dfxGuidelines.size(); k++){
				weightsSum+=colWeights[k];
			}
			
			for(int k=0; k<dfxGuidelines.size(); k++){
				results[k] = (colWeights[k]/weightsSum)*100;
			}
			
			qfdResults = results;
		}
				
		return (float[])qfdResults;
	}
	
	public static List<DfXImportances> getImportancesByProdId(int productId){
		Session session = HibernateUtil.currentSession();
		Query q = session.createQuery("select i from DfXImportances i where i.product.id=:productId");
		q.setInteger("productId", productId);
		return q.list();
	}

}
